#pragma once

#include <iostream>
#include <sys/time.h>
#include "Socket.hpp"
#include <poll.h>

const int defaultfd = -1;
const uint16_t defaultport = 8800;
const int fd_max = 64; // fd_set 内部又一个位图，这个位图的大小是有限的，而poll数组是无限的，
// 所有fd也是无限的，前提不能超过系统所能打开的最大文件数目。
class Pollserver:public Nocopy
{
public:
    Pollserver()
    {
        for (int i = 0; i < fd_max; i++)
        {
            fd_events[i].fd = defaultfd;
            fd_events[i].events = 0;
            fd_events[i].revents = 0;
        }
    }

    void Init()
    {
        listen_.Socket();
        listen_.Bind(defaultport);
        listen_.Listen();
    }

    void Accpter()
    {
        string ip;
        uint16_t port;

        int n = listen_.Accpect(&ip, &port);
        if (n < 0)
            return;

        lg("info", "accpect success ip=%s,port=%d,fd=%d", ip.c_str(), port, n);

        int i;
        for (i = 1; i < fd_max; i++)
        {
            if (fd_events[i].fd != defaultfd)
                continue;
            else
                break;
        }

        if (i == fd_max)
        {
            lg("Warning", "fd full");
            close(n);
            return ;
        }
        else
        {
            fd_events[i].fd = n;//添加
            fd_events[i].events = POLLIN;
        }

        fd_events[0].events = POLLIN;
        fd_events[0].revents = defaultfd; // 恢复listen的现场
    }

    void Recev(int pos)
    {
        cout<<"read"<<endl;
        int fd = fd_events[pos].fd;
        char buffer[1024];
        int n = read(fd, buffer, sizeof(buffer)-1);
        if (n < 0)
        {
            lg("Warning", "read error");
            close(fd);
            fd_events[pos].fd = defaultfd;
            fd_events[pos].events = 0;
            fd_events[pos].revents = 0;
            return;
        }
        else if (n == 0)
        {
            lg("Info", "read over");
            close(fd);
            fd_events[pos].fd = defaultfd;
            fd_events[pos].events = 0;
            fd_events[pos].revents = 0;
            return;
        }
        else 
        {
            buffer[n]=0;
            cout<<"get a message "<<buffer<<endl;

            fd_events[pos].revents = 0;//继续使用
        }
    }

    void Dispatch(int num)
    {
        int count = 0;
        for (int i = 0; i < fd_max; i++)
        {
            if ((fd_events[i].fd != defaultfd) && (fd_events[i].revents ==POLLIN))
            {
                count++;
                if (fd_events[i].fd ==listen_.Fd()) // 有新的链接
                {
                    Accpter();
                }
                else
                {
                    Recev(i);
                }

                if (count == num)
                    return; // 这说明了，就绪的个数已经完成了
            }
        }
    }

    void Start()
    {
        int listenfd = listen_.Fd();
        fd_events[0].fd = listenfd;
        fd_events[0].events = POLLIN;
        for (;;)
        {
            int n = poll(fd_events, fd_max, 2000);
            if (n < 0)
            {
                lg("warning","poll error ");
            }
            else if (n == 0)
            {
                lg("info", "not fd ready");
            }
            else
            {
                lg("info", "get link or data");
                //
                Dispatch(n);
                Print();
            }
        }
    }

    void Print()
    {
        cout<<"online link: ";
        for(int i=0;i<fd_max;i++)
        {
            if(fd_events[i].fd!=defaultfd)
            {
                cout<<fd_events[i].fd<<" ";
            }
        }
        cout<<endl;
    }

private:
    Sock listen_;
    struct pollfd fd_events[fd_max];
};